﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.Serialization;
using Microsoft.Practices.Prism.Mvvm;
using Interfaces;

namespace Services
{
    [DataContract]
    public class ChartResult : INotifyPropertyChanged, IChartResult
    {
        [DataMember] public DateTime DateTime { get { return _time; } set { _time = value; NotifyPropertyChanged("DateTime"); } }
        [DataMember] public float Close { get { return _close; } set { _close = value; NotifyPropertyChanged("Close"); } }
        [DataMember] public float High { get { return _high; } set { _high = value; NotifyPropertyChanged("High"); } }
        [DataMember] public float Low { get { return _low; } set { _low = value; NotifyPropertyChanged("Open"); } }
        [DataMember] public float Open { get { return _open; } set { _open = value; NotifyPropertyChanged("Interval"); } }
        [DataMember] public float Volume { get { return _volume; } set { _volume = value; NotifyPropertyChanged("Volume"); } }
        [DataMember] public float Change { get { return _change; } set { _change = value; NotifyPropertyChanged("Change"); } }
        [DataMember] public float Range { get { return _range; } set { _range = value; NotifyPropertyChanged("Range"); } }
        [DataMember] public float Diff { get { return _diff; } set { _diff = value; NotifyPropertyChanged("Diff"); } }
        [DataMember] public bool Up { get { return _up; } set { _up = value; NotifyPropertyChanged("Up"); } }

        public event PropertyChangedEventHandler PropertyChanged;

        private float _close = float.MinValue, _high = float.MinValue, _low = float.MaxValue, _open = float.MinValue, _volume, _change, _range, _diff;
        private DateTime _time = DateTime.MinValue;
        private bool _up;

        public void Update(DateTime start, int marketOpenMinute, int interval, string[] row, bool isFirstRow, IChartResult max = null)
        {
            SetTime(start, marketOpenMinute, interval, row, isFirstRow);
            SetValues(row);
            if (max != null) UpdateSum(max);
        }

        private void SetTime(DateTime start, int marketOpenMinute, int interval, string[] row, bool isFirstRow)
        {
            if (isFirstRow)
                _time = DateTime.FromOADate(int.Parse(row[0].TrimStart('a')) / 86400 + 25569 + (5.5 / 24)).AddMinutes(marketOpenMinute);
            else
                _time = start.AddSeconds(int.Parse(row[0]) * interval);
        }

        private void SetValues(string[] row)
        {
            float.TryParse(row[1], out _close);
            float.TryParse(row[2], out _high);
            float.TryParse(row[3], out _low);
            float.TryParse(row[4], out _open);
            float.TryParse(row[5], out _volume);
            _up = _close >= _open ? true : false;
            _change = Math.Abs(_open - _close);
            _range = _high - _low;
            _diff = _range - _change;
        }

        private void UpdateSum(IChartResult result)
        {
            if (result.Open == float.MinValue) result.Open = Open;
            if (result.High < High) result.High = High;
            if (result.Low > Low) result.Low = Low;
            result.Volume += Volume;
            result.Close = Close;
        }

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}
